/*  $OpenBSD: vfprintf.c,v 1.71 2016/01/04 15:47:47 schwarze Exp $  */
/* -
 * Copyright (c) 1990 The Regents of the University of California.
 * All rights reserved.
 *
 * This code is derived from software contributed to Berkeley by
 * Chris Torek.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the University nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include "los_config.h"
#ifdef LOSCFG_LIB_LIBC
#include "string.h"
#include "stdlib.h"
#endif
#ifdef LOSCFG_LIB_LIBCMINI
#include "libcmini.h"
#endif
#include "hisoc/uart.h"
#ifdef LOSCFG_FS_VFS
#include "console.h"
#endif
#ifdef LOSCFG_SHELL_DMESG
#include "dmesg.ph"
#endif

/*lint -e42 -e40 -e52 -e529 -e611 -e578 -e539 -e63*/
extern int finite(double x);
extern ssize_t write(int fd, const void *buf, size_t nbytes);
typedef void (*PUTC_FUNC)(unsigned n, void *cookie);

#define  SIZEBUF  256

#define LIBC_STDIO_PRINTF_FLOATING_POINT
#ifdef LIBC_STDIO_PRINTF_FLOATING_POINT
#ifdef LOSCFG_LIB_LIBM
#include "float.h"
#include "math.h"
#endif

/* NOTICE! FOR FULL FLOAT SUPPROT,
   delete or commente the following line
*/
#define SMALL_NUMBER_BUFFER

/* NOTICE! IF STACK IS SMALL, delete or commente the following line,
   then the system will use malloc memory instead
*/
#define USE_STACK_BUFFER

#ifndef USE_STACK_BUFFER
#include "stdlib.h"
#endif

#define MAXEXPINDEX 20
#if defined(SMALL_NUMBER_BUFFER) && defined(USE_STACK_BUFFER)
#define FRACT_MAX_SIZE  20
#define EXP_MAX_SIZE    20
#define BUFFER_SIZE             (EXP_MAX_SIZE + FRACT_MAX_SIZE + 1 + 1)     /* + decimal point */
#else
#define FRACT_MAX_SIZE  20
#define EXP_MAX_SIZE    309
#define BUFFER_SIZE             (EXP_MAX_SIZE + FRACT_MAX_SIZE + 1 + 1)     /* + decimal point */
#endif

#define DEFPREC         6

typedef union
{
    INT32 asi32[2];

    INT64 asi64;

    double value;

    struct
    {
        unsigned int fraction3:16;
        unsigned int fraction2:16;
        unsigned int fraction1:16;
        unsigned int fraction0: 4;
        unsigned int exponent :11;
        unsigned int sign     : 1;
    }number;

    struct
    {
        unsigned int function3:16;
        unsigned int function2:16;
        unsigned int function1:16;
        unsigned int function0:3;
        unsigned int quiet:1;
        unsigned int exponent: 11;
        unsigned int sign : 1;
    }nan;

    struct
    {
        UINT32 lsw;
        UINT32 msw;
    }parts;

}libm_ieee_double_shape_type;

#else

#define BUFFER_SIZE 40

#endif


#define DIGIT_BIG_HEX  "0123456789ABCDEF"
#define DIGIT_HEX  "0123456789abcdef"

#define ALT_FROM                   (1)                         /* alternate form */
#define PREFIX_HEX               (1U<<1)                  /* add 0x or 0X prefix */
#define LEFT_ADJ                   (1U<<2)                  /* left adjustment */
#define LONG_DOUBLE           (1U<<3)                   /* long double; unimplemented */
#define LONG_INT                  (1U<<4)                  /* long integer */
#define QUAD_INT                 (1U<<5)                   /* quad integer */
#define SHOR_TINT                (1U<<6)                  /* short integer */
#define ZERO_PAD                 (1U<<7)                  /* zero (as opposed to blank) pad */
#define FLOAT_POINT_NUM     (1U<<8)                  /* Floating point number */
#define SIZE_T                      (1U<<9)                  /* size_t */


#define char_to_digit(c)     ((c) - '0')
#define char_is_digit(c)     ((unsigned)char_to_digit(c) <= 9)
#define digit_to_char(n)      ((n) + '0')

#define PAD_CNT 32             /* pad chunk size */


typedef unsigned long long U64_QUAD_T;
typedef unsigned  long ULONG;

#define SARG() \
    (converFlag&QUAD_INT ? va_arg(vaArg, signed long long) : \
    converFlag&LONG_INT ? va_arg(vaArg, long) : \
    converFlag&SHOR_TINT ? (long)(short)va_arg(vaArg, int) : \
    converFlag&SIZE_T ? (long)va_arg(vaArg, size_t) : \
    (long)va_arg(vaArg, int));

#define UARG() \
    (converFlag&QUAD_INT ? va_arg(vaArg, U64_QUAD_T) : \
     converFlag&LONG_INT ? va_arg(vaArg, ULONG) : \
     converFlag&SHOR_TINT ? (ULONG)(unsigned short)va_arg(vaArg, int) : \
     converFlag&SIZE_T ? va_arg(vaArg, size_t) : \
     (ULONG)va_arg(vaArg, unsigned int))

#define PRINT(ptr,len)            \
    do{                                \
        if (pFputc == NULL)             \
            break;                      \
        int tmp_len = (len);                \
        char* tmp_ptr = (ptr);                \
        while(tmp_len--)                    \
            pFputc(*tmp_ptr++,cookie);    \
    }while(0)                        \


#define PAD(size, with)                                                   \
    do{                                                              \
        x = (size);                                                    \
        if (x  > 0) {                                               \
            while (x > PAD_CNT) {                                                \
                PRINT(with, PAD_CNT);                                            \
                x -= PAD_CNT;                                                    \
            }                                                                    \
            PRINT(with, x);                                                      \
        }                                                                        \
    }while(0)

#define COPY_PAD(size, with)                                        \
    do {                                                            \
        x = (size);                                                 \
        if (x > 0) {                                                \
            while (x > PAD_CNT) {                                   \
                x -= PAD_CNT;                                       \
                tp_len = __cp(str, (with), PAD_CNT, ret, wBufLen);  \
                str +=  tp_len;                                     \
                ret += tp_len;                                      \
            }                                                       \
            tp_len = __cp(str, (with), x, ret, wBufLen);            \
            str +=  tp_len;                                         \
            ret += tp_len;                                          \
        }                                                           \
    } while (0)

#define DMESG_PAD(size, with)                                        \
    do{                                                                 \
        x = (size);                                                    \
        if (x > 0) {                                          \
            while (x > PAD_CNT) {                                       \
                (VOID)osLogMemcpyRecord(with, PAD_CNT);                 \
                x -= PAD_CNT;                                           \
            }                                                           \
            (VOID)osLogMemcpyRecord(with, x);                           \
        }                                                               \
    }while(0)

int __cp(char *dst, char *src, int len,int size, int wBufLen)
{
    char *temp_dst = dst;
    char *temp_src = src;
    int temp_len = len;
    int i= 0;

    if(len <= 0)
    {
        return 0;
    }

    while (temp_len--)
    {
        if(i >= wBufLen- size -2)
        {
            return temp_dst - dst;
        }

        if(*temp_src == '\n')
        {
            *temp_dst++ = '\r';
            i++;
            if(i >= wBufLen - size -2)
            {
                return temp_dst - dst;
            }
        }

        *temp_dst++ = *temp_src++;
        i++;
    }

    return temp_dst - dst;
}

int hex2asc(int n)
{
    n = (unsigned int)n & 15;
    if(n > 9){
        return ('a' - 10) + n;
    } else {
        return '0' + n;
    }
}

void dputs(const char *s, void (*pFputc)(unsigned n, void *cookie), void *cookie)
{
    while (*s) {
        pFputc(*s++, cookie);
    }
}

#ifdef LIBC_STDIO_PRINTF_FLOATING_POINT

    static char *
_round_up(double fract, int *expo, char *start, char *end, char ch, char *signp)
{
    double c;
    char * bound = end;
    char * begin  = start;

    if (!fract)
        c = char_to_digit(ch);
    else
        (void)modf(fract * 10, &c);

    if (c > 4)
        for (;; --bound) {
            if (*bound == '.')
                --bound;
            if (++*bound <= '9')
                break;
            *bound = '0';
            if (bound == begin) {
                if (expo == NULL) {
                    *--bound = '1';
                    --begin;
                }
                else {
                    *bound = '1';
                    ++*expo;
                }
                break;
            }
        }

    else if (*signp == '-')
        for (;; --bound) {
            if (*bound == '.')
                --bound;
            if (*bound != '0')
                break;
            if (bound == begin)
                *signp = 0;
        }
    return (begin);
}

    static char *
index(char *pbuf, int expo, int fmtch)
{
    char *t = NULL;
    char expbuf[MAXEXPINDEX];

    *pbuf++ = fmtch;
    if (expo >= 0)
        *pbuf++ = '+';
    else {
        expo = -expo;
        *pbuf++ = '-';
    }

    t = expbuf + MAXEXPINDEX;
    if (expo <= 9) {
        *pbuf++ = '0';
        *pbuf++ = digit_to_char(expo);
    }
    else {
        do {
            *--t = digit_to_char(expo % 10);
        } while ((expo /= 10) > 9);
        *--t = digit_to_char(expo);
        for (; t < expbuf + MAXEXPINDEX; *pbuf++ = *t++);
    }
    return (pbuf);
}


static int
numToString(double num, int precede, unsigned int action, char *ptrSign, int fmtch, char *startp,
        char *endp)
{
    libm_ieee_double_shape_type ieeetype;
    char *pdata = startp;

    ieeetype.value = num;
    *ptrSign = 0;
    if ( ieeetype.number.sign ){  // this checks for <0.0 and -0.0
        *ptrSign = '-';
        num = -num;
    }

    if (!finite(num)) {
        unsigned adjustment;
        if (fmtch == 'f' || fmtch == 'g' || fmtch == 'e') {
            adjustment = 'a' - 'A';
        }
        else {
            adjustment = 0;
        }

        if (!isnan(num)) {  /*lint  !e506*/ // infinite
            *pdata++ = 'I' + adjustment;
            *pdata++ = 'N' + adjustment;
            *pdata++ = 'F' + adjustment;
        }
        else {
            *pdata++ = 'N' + adjustment;
            *pdata++ = 'A' + adjustment;
            *pdata++ = 'N' + adjustment;
        }
    }
    else {
        char *pbuf = NULL;
        double fract;
        int dotch, expcount, gfmt;
        double idx, bcdNum;

        fract = modf(num, &idx);
        dotch = expcount = gfmt = 0;

        pdata = ++startp;

        pbuf = endp - 1;
        for (; (idx && (pbuf > startp)); ) {
            bcdNum = modf(idx / 10, &idx);
            *pbuf-- = digit_to_char((int)((bcdNum + .01) * 10));
            ++expcount;
            if (expcount >= EXP_MAX_SIZE) break;
        }

        if (expcount >= EXP_MAX_SIZE && idx)
        {
            PRINT_ERR("%s, %d, failed to convert num to str, try undef SMALL_NUMBER_BUFFER \n", __FUNCTION__, __LINE__);
        }

        switch (fmtch) {
            case 'E':
            case 'e':
efmt:
                if (expcount) {
                    *pdata++ = *++pbuf;
                    if (precede || action&ALT_FROM)
                        *pdata++ = '.';

                    for (; precede && ++pbuf < endp; --precede)
                        *pdata++ = *pbuf;

                    if (!precede && ++pbuf < endp) { /*lint !e662*/
                        startp = _round_up((double)0, &expcount, startp,
                                pdata - 1, *pbuf, ptrSign);
                        fract = 0;
                    }
                    --expcount;
                }
                else if (!fract) {
                    *pdata++ = '0';
                    if (precede || action&ALT_FROM)
                        *pdata++ = '.';
                }
                else {
                    for (expcount = -1;; --expcount) {
                        fract = modf(fract * 10, &bcdNum);
                        if (bcdNum)
                            break;
                    }
                    *pdata++ = digit_to_char((int)bcdNum);
                    if (precede || action&ALT_FROM)
                        *pdata++ = '.';
                }

                if (fract) {
                    if (precede)
                        do {
                            fract = modf(fract * 10, &bcdNum);
                            *pdata++ = digit_to_char((int)bcdNum);
                        } while (--precede && fract);
                    if (fract)
                        startp = _round_up(fract, &expcount, startp,
                                pdata - 1, (char)0, ptrSign);
                }
                for (; precede-- && pdata < endp; *pdata++ = '0');

                if (gfmt && !(action&ALT_FROM)) {
                    while (pdata > startp && *--pdata == '0');
                    if (*pdata == '.')
                        --pdata;
                    ++pdata;
                }
                pdata = index(pdata, expcount, fmtch);
                break;
            case 'f':
                if (!expcount)
                    *pdata++ = '0';
                else
                    for (; ++pbuf < endp; *pdata++ = *pbuf);


                if (precede || action&ALT_FROM)
                    *pdata++ = '.';

                if (fract) {
                    if (precede)
                        do {
                            fract = modf(fract * 10, &bcdNum);
                            *pdata++ = digit_to_char((int)bcdNum);
                        } while (--precede && fract);
                    if (fract)
                        startp = _round_up(fract, (int *)NULL, startp,
                                pdata - 1, (char)0, ptrSign);
                }
                for (; precede-- && pdata < endp; *pdata++ = '0');
                break;
            case 'g':
            case 'G':

            if (!precede)
                    ++precede;

                if (expcount > precede || (!expcount && fract && fract < .0001)) {
                    --precede;
                    gfmt = 1;
                    fmtch -= 2;             /* from G to E or g to e */
                    goto efmt;
                }

                if (!expcount)
                    *pdata++ = '0';
                else
                    for (; ++pbuf < endp; *pdata++ = *pbuf, --precede);

                if (precede || action&ALT_FROM) {
                    *pdata++ = '.';
                    dotch = 1;
                }
                else
                    dotch = 0;

                if (fract) {
                    if (precede) {
                        do {
                            fract = modf(fract * 10, &bcdNum);
                            *pdata++ = digit_to_char((int)bcdNum);
                        } while(!bcdNum);
                        while (--precede && fract) {
                            fract = modf(fract * 10, &bcdNum);
                            *pdata++ = digit_to_char((int)bcdNum);
                        }
                    }
                    if (fract)
                        startp = _round_up(fract, (int *)NULL, startp,
                                pdata - 1, (char)0, ptrSign);
                }
                if (action&ALT_FROM)
                    for (; precede-- && pdata < endp; *pdata++ = '0');
                else if (dotch) {
                    while (pdata > startp && *--pdata == '0');
                    if (*pdata != '.')
                        ++pdata;
                }
        }
    }
    return (pdata - startp);
}

#endif
#ifdef LOSCFG_NET_TELNET
extern volatile UINT32 g_telnetMask; /*lint !e18*/
extern int telnet_client_fd;

int telnet_Mask(void)
{
    return g_telnetMask;
}
#endif

static int __dprintf(const char *fmt, va_list vaArg,
        PUTC_FUNC pFputc,char *cookie, int wBufLen)
{
    char *format = NULL;
    char *cp = NULL;
    int ch;
    int x,y;
    unsigned int converFlag = 0;
    int ret;
    int nWidth;
    int precede;
    char chSign;
    UINT32 wc;

    U64_QUAD_T quad;
    enum {OCT,DEC,HEX} base = OCT;
    int dprec = 0;
    int fldSize;
    int realSize;
    int size;
    char *digit = (char *)NULL;


#ifdef USE_STACK_BUFFER
    char buffer[BUFFER_SIZE];
#else
    char *buffer = NULL;
#endif

    char ox[2];
#ifdef LIBC_STDIO_PRINTF_FLOATING_POINT
    char softsign;
    double bigNum;
    int fpprecede;
#endif

    char *str = cookie;
    int tp_len = 0;

    static char blanks[PAD_CNT];
    static char zeroes[PAD_CNT];

#ifndef USE_STACK_BUFFER
    buffer = (char*)malloc(BUFFER_SIZE*sizeof(char));
    if (NULL == buffer)
    {
        return -1;
    }
#endif

    (void)memset_s(blanks, PAD_CNT, ' ', PAD_CNT);
    (void)memset_s(zeroes, PAD_CNT, '0', PAD_CNT);

    format = (char*)fmt;
    ret = 0;

    for(;;){
        cp = (char*)format;
        x = 0;
        while ((wc = *format) != 0) {
            format++;
            if (wc == '%') {
                format--;
                x = 1;
                break;
            }
        }

        if ((y = format - cp) != 0) {
#ifdef LOSCFG_SHELL_DMESG
            if(!osCheckUartLock())
                PRINT(cp,y);/*lint -e42 -e40 -e52*/
            (void)osLogMemcpyRecord(cp,y);
#else
            PRINT(cp,y);/*lint -e42 -e40 -e52*/
#endif
            tp_len = __cp(str,cp,y,ret, wBufLen);
            str += tp_len;
            ret += tp_len;
        }

        if((x <= 0))
        {
            *++str = '\0';   /*lint !e661*/
#ifndef USE_STACK_BUFFER
            free(buffer);
#endif
            return ret+1;
        }

        format++;
        converFlag = 0;
        dprec = 0;
#ifdef LIBC_STDIO_PRINTF_FLOATING_POINT
        fpprecede = 0;
#endif
        chSign = '\0';
        precede = -1;
        nWidth = 0;

reflag:
        ch = *format++;
reswitch:
        switch (ch) {
                case '*':
                    if ((nWidth = va_arg(vaArg, int)) >= 0)
                        goto reflag;
                    nWidth = -nWidth;
                    /*lint -fallthrough */
                case '-':
                    converFlag |= LEFT_ADJ;
                    goto reflag;
                case ' ':
                    if(!chSign)
                        chSign = ' ';
                    goto reflag;
                case '.':
                    if ((ch = *format++) == '*') {
                        x = va_arg(vaArg, int);
                        precede = x < 0 ? -1 : x;
                        goto reflag;
                    }
                    x = 0;
                    while (char_is_digit(ch)) {
                        x = 10 * x + char_to_digit(ch);
                        ch = *format++;
                    }
                    precede = x < 0 ? -1 : x;
                    goto reswitch;
                case '#':
                    converFlag |= ALT_FROM;
                    goto reflag;
                case '+':
                    chSign = '+';
                    goto reflag;
#ifdef LIBC_STDIO_PRINTF_FLOATING_POINT
                case 'L':
                    converFlag |= LONG_DOUBLE;
                    goto reflag;
#endif
                case '0':
                    converFlag |= ZERO_PAD;
                    goto reflag;
                case '1': case '2': case '3': case '4':
                case '5': case '6': case '7': case '8': case '9':
                    x = 0;
                    do {
                        x = 10 * x + char_to_digit(ch);
                        ch = *format++;
                    } while (char_is_digit(ch));
                    nWidth = x;
                    goto reswitch;
                case 'h':
                    converFlag |= SHOR_TINT;
                    goto reflag;
                case 'l':
                    if (*format == 'l') {
                        format++;
                        converFlag |= QUAD_INT;
                    } else {
                        converFlag |= LONG_INT;
                    }
                    goto reflag;
                case 'q':
                    converFlag |= QUAD_INT;
                    goto reflag;
                case 'c':
                    *(cp = buffer) = va_arg(vaArg, int);
                    size = 1;
                    chSign = '\0';
                    break;
#ifdef LIBC_STDIO_PRINTF_FLOATING_POINT
                case 'e':
                case 'E':
                case 'f':
                case 'g':
                case 'G':
                    bigNum = va_arg(vaArg, double);
                    if (precede > FRACT_MAX_SIZE) {
                        if ((ch != 'g' && ch != 'G' && ch != 'e' && ch != 'E') || (converFlag&ALT_FROM))
                        {
                            if (!finite(bigNum)) {
                                fpprecede = 0;
                            }
                            else {
                                fpprecede = precede - FRACT_MAX_SIZE;
                            }
                        }
                        precede = FRACT_MAX_SIZE;
                    } else if (precede == -1)
                        precede = DEFPREC;
                    cp = buffer;
                    *cp = '\0';
#ifndef USE_STACK_BUFFER
                    size = numToString(bigNum, precede, converFlag, &softsign, ch,cp, buffer + BUFFER_SIZE);
#else
                    size = numToString(bigNum, precede, converFlag, &softsign, ch,cp, buffer + sizeof(buffer));
#endif

                    if (softsign)
                        chSign = '-';
                    if (*cp == '\0')
                        cp++;
                    break;
#else
                case 'e':
                case 'E':
                case 'f':
                case 'g':
                case 'G':
                    (void) va_arg(vaArg, double);
                    cp = "";
                    size = 0;
                    chSign = '\0';
                    break;
#endif
                case 'O':
                    converFlag |= LONG_INT;
                    /*lint -fallthrough */
                case 'o':
                    quad = UARG();
                    base = OCT;
                    goto nosign;
                case 'D':
                    converFlag |= LONG_INT;
                    /*lint -fallthrough */
                case 'd':
                case 'i':
                    quad = SARG();
#ifndef _NO_LONGLONG
                    if ((long long)quad < 0)
#else
                        if ((long) quad < 0)
#endif
                        {
                            quad = (~quad + 1);
                            chSign = '-';
                        }
                    base = DEC;
                    goto number;
                case 'U':
                    converFlag |= LONG_INT;
                    /*lint -fallthrough */
                case 'u':
                    quad = UARG();
                    base = DEC;
                    goto nosign;

                /*lint -e48*/
                case 'n':
#ifndef ___NO_LONGLONG
                    if (converFlag & QUAD_INT)
                        *va_arg(vaArg, long long *) = ret;
                    else
#endif
                        if (converFlag & LONG_INT)
                            *va_arg(vaArg, long *) = ret;
                        else if (converFlag & SHOR_TINT)
                            *va_arg(vaArg, short *) = ret;
                        else if (converFlag & SIZE_T)
                            *va_arg(vaArg, size_t *) = ret;
                        else
                            *va_arg(vaArg, int *) = ret;
                    continue;
                /*lint +e48*/
                case 's':
                    if ((cp = va_arg(vaArg, char *)) == NULL) /*lint !e64*/
                        cp = (char *)"(null)";
                    if (precede >= 0) {
                        char *p = (char *)memchr(cp, 0, precede);
                        if (p != NULL) {
                            size = p - cp;
                            if (size > precede)
                                size = precede;
                        } else
                            size = precede;
                    } else
                        size = strlen(cp);
                    chSign = '\0';
                    break;
                case 'p':
                    quad = (AARCHPTR)va_arg(vaArg, void *);
                    base = HEX;
                    digit = (char *)DIGIT_HEX;
                    converFlag |= PREFIX_HEX;
                    ch = 'x';
                    goto nosign;
                case 'z':
                    converFlag |= SIZE_T;
                    goto reflag;
                case 'X':
                    digit = (char *)DIGIT_BIG_HEX;
                    goto hex;
                case 'x':
                    digit = (char *)DIGIT_HEX;
hex:            quad = UARG();
                base = HEX;
                if (converFlag & ALT_FROM && quad != 0)
                    converFlag |= PREFIX_HEX;
nosign:         chSign = '\0';

number:         if ((dprec = precede) >= 0)
                    converFlag &= ~ZERO_PAD;
                cp = buffer + BUFFER_SIZE;
                if (quad != 0 || precede != 0) {
                    switch(base){
                        case DEC:
                            if(converFlag & QUAD_INT) {
                                while (quad >= 10) {
                                    U64_QUAD_T next = quad / 10;
                                    *--cp = digit_to_char(quad - (next * 10));
                                    quad = next;
                                }
                                *--cp = digit_to_char(quad);
                            }
                            else {
                                ULONG v = (ULONG)quad;
                                while (v >= 10) {
                                    ULONG next = v / 10;
                                    *--cp = digit_to_char(v - (next * 10));
                                    v = next;
                                }
                                *--cp = digit_to_char(v);
                            }
                            break;
                        case HEX:
                            do {
                                *--cp = digit[quad & 15]; /*lint !e613*/
                                quad >>= 4;
                            } while (quad);
                            break;
                        case OCT:
                            do{
                                *--cp = digit_to_char(quad & 7);
                                quad >>= 3;
                            }while(quad);
                            if (converFlag & ALT_FROM && *cp != '0')
                                *--cp = '0';
                            break;
                        default:
                            cp = (char *)"bug in __dprintf: bad base";
                            size = strlen(cp);
                            goto skipsize;
                    }
                }//end if(_uquad
                size = buffer + BUFFER_SIZE - cp;
skipsize:
                break;
                default:
                if (ch == '\0')
                {
#ifndef USE_STACK_BUFFER
                    free(buffer);
#endif
                    return ret;
                }
                cp = buffer;
                *cp = ch;
                size = 1;
                chSign = '\0';
                break;
            }//end switch(ch)..
#ifdef LIBC_STDIO_PRINTF_FLOATING_POINT
            fldSize = size + fpprecede;
#else
            fldSize = size;
#endif
            if (chSign)
                fldSize++;
            else if (converFlag & PREFIX_HEX)
                fldSize+= 2;
            realSize = dprec > fldSize ? dprec : fldSize;

            if ((converFlag & (LEFT_ADJ|ZERO_PAD)) == 0) {
                if (nWidth - realSize > 0) {
#ifdef LOSCFG_SHELL_DMESG
                    if(!osCheckUartLock())
                        PAD(nWidth - realSize, blanks);/*lint -e42 -e40 -e52*/
                    DMESG_PAD(nWidth - realSize, blanks);
#else
                    PAD(nWidth - realSize, blanks);/*lint -e42 -e40 -e52*/
#endif
                    COPY_PAD(nWidth - realSize, blanks);
                }
            }

            if (chSign) {
                {
#ifdef LOSCFG_SHELL_DMESG
                    if(!osCheckUartLock())
                        PRINT(&chSign, 1);/*lint -e42 -e40 -e52*/
                    (void)osLogMemcpyRecord(&chSign, 1);
#else
                    PRINT(&chSign, 1);/*lint -e42 -e40 -e52*/
#endif
                }
                tp_len = __cp(str,&chSign,1,ret, wBufLen);
                str += tp_len;
                ret+=tp_len;
            } else if (converFlag & PREFIX_HEX) {
                ox[0] = '0';
                ox[1] = ch;
#ifdef LOSCFG_SHELL_DMESG
                if(!osCheckUartLock())
                    PRINT(ox, 2);/*lint -e42 -e40 -e52*/
                (void)osLogMemcpyRecord(ox, 2);
#else
                PRINT(ox, 2);/*lint -e42 -e40 -e52*/
#endif
                tp_len = __cp(str, ox, 2, ret, wBufLen);
                str += tp_len;
                ret += tp_len;
            }

            if ((converFlag & (LEFT_ADJ|ZERO_PAD)) == ZERO_PAD) {
                if (nWidth - realSize > 0) {
#ifdef LOSCFG_SHELL_DMESG
                    if(!osCheckUartLock())
                        PAD(nWidth - realSize, zeroes);/*lint -e42 -e40 -e52*/
                    DMESG_PAD(nWidth - realSize, zeroes);
#else
                    PAD(nWidth - realSize, zeroes);/*lint -e42 -e40 -e52*/
#endif
                    COPY_PAD(nWidth - realSize, zeroes);
                }
            }

            if (dprec - fldSize > 0) {
#ifdef LOSCFG_SHELL_DMESG
                if(!osCheckUartLock())
                    PAD(dprec - fldSize, zeroes);/*lint -e42 -e40 -e52*/
                DMESG_PAD(dprec - fldSize, zeroes);
#else
                PAD(dprec - fldSize, zeroes);/*lint -e42 -e40 -e52*/
#endif
                COPY_PAD(dprec - fldSize, zeroes);
            }
#ifdef LOSCFG_SHELL_DMESG
            if(!osCheckUartLock())
                PRINT(cp, size);/*lint -e42 -e40 -e52*/
            (void)osLogMemcpyRecord(cp, size);
#else
            PRINT(cp, size);/*lint -e42 -e40 -e52*/
#endif
            tp_len = __cp(str,cp,size,ret, wBufLen);
            ret += tp_len;
            str += tp_len;
#ifdef LIBC_STDIO_PRINTF_FLOATING_POINT
            if(fpprecede > 0)
            {
#ifdef LOSCFG_SHELL_DMESG
                if(!osCheckUartLock())
                    PAD(fpprecede, zeroes);/*lint -e42 -e40 -e52*/
                DMESG_PAD(fpprecede, zeroes);
#else
                PAD(fpprecede, zeroes);/*lint -e42 -e40 -e52*/
#endif
                COPY_PAD(fpprecede, zeroes);
            }
#endif
            if (converFlag & LEFT_ADJ) {
                if (nWidth - realSize > 0) {
#ifdef LOSCFG_SHELL_DMESG
                    if(!osCheckUartLock())
                        PAD(nWidth - realSize, blanks);/*lint -e42 -e40 -e52*/
                    DMESG_PAD(nWidth - realSize, blanks);
#else
                    PAD(nWidth - realSize, blanks);/*lint -e42 -e40 -e52*/
#endif
                    COPY_PAD(nWidth - realSize, blanks);
                }
            }
    }
}


void _dprintf(const char *fmt, va_list ap)
{
#ifdef USE_STACK_BUFFER
    char buffer[SIZEBUF];
#else
    char *buffer = NULL;
#endif

#ifndef USE_STACK_BUFFER
    buffer = (char*)malloc(SIZEBUF*sizeof(char));
    if (NULL == buffer)
    {
        PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
        return;
    }
#endif

    (void)__dprintf(fmt, ap, (PUTC_FUNC)uart_fputc, buffer, SIZEBUF);

#ifndef USE_STACK_BUFFER
    free(buffer);
#endif

}

__attribute__ ((noinline)) void dprintf(const char *fmt, ...)
{
    PUTC_FUNC pfn_put = (PUTC_FUNC)uart_fputc;
    va_list ap;
    int wBufLen;
    char *bbuf = NULL;
#ifdef LOSCFG_PLATFORM_CONSOLE
    int wLen;
#endif
#ifdef USE_STACK_BUFFER
    char abuf[SIZEBUF];
    bbuf = abuf;
#else
    bbuf = (char*)malloc(SIZEBUF);
    if (bbuf == NULL) {
        PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
        return;
    }
#endif
    wBufLen = SIZEBUF;

    va_start(ap, fmt); /*lint !e530*/

#ifdef LOSCFG_PLATFORM_CONSOLE
    if (console_enable())
    {
        pfn_put = NULL;
    }
    wLen = __dprintf(fmt, ap, pfn_put, bbuf, wBufLen);
    if (pfn_put == NULL)
    {
        while (wLen >= wBufLen - 1)
        {
#ifdef USE_STACK_BUFFER
            if (wBufLen != SIZEBUF)
                free(bbuf);  /*lint !e424*/
#else
            free(bbuf);
#endif

            wBufLen = (unsigned int)wBufLen << 1;
            if (wBufLen <= 0)
            {
                PRINT_ERR("%s, %d, length overflow!\n", __FUNCTION__, __LINE__);
                va_end(ap);
                return;
            }

            bbuf = (char*)malloc(wBufLen);
            if (NULL == bbuf)
            {
                PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
                va_end(ap);
                return;
            }
            wLen = __dprintf(fmt, ap, pfn_put, bbuf, wBufLen);
        }
        *(bbuf + wLen - 1) = 0;
        (VOID)write(STDOUT, bbuf, wLen);
    }
#else
    (VOID)__dprintf(fmt, ap, pfn_put, bbuf, wBufLen);
#endif
#ifdef USE_STACK_BUFFER
    if (wBufLen != SIZEBUF)
        free(bbuf); /*lint !e673*/
#else
    free(bbuf);
#endif


    va_end(ap);
} /*lint !e438 !e593*/

void lk_dprintf(const char *fmt, va_list ap)
{
    PUTC_FUNC pfn_put = (PUTC_FUNC)uart_fputc;
#ifdef LOSCFG_PLATFORM_CONSOLE
    int wLen;
#endif
    int wBufLen;
    char *bbuf = NULL;
#ifdef USE_STACK_BUFFER
    char abuf[SIZEBUF];
    bbuf = abuf;
#else
    bbuf = (char*)malloc(SIZEBUF);
    if (bbuf == NULL) {
        PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
        return;
    }
#endif
    wBufLen = SIZEBUF;

#ifdef LOSCFG_PLATFORM_CONSOLE
    if (console_enable() == TRUE)
    {
        pfn_put = NULL;
    }
    wLen = __dprintf(fmt, ap, pfn_put, bbuf, wBufLen);
    if (pfn_put == NULL)
    {
        while (wLen >= wBufLen - 1)
        {
#ifdef USE_STACK_BUFFER
            if (wBufLen != SIZEBUF)
                free(bbuf);  /*lint !e424*/
#else
            free(bbuf);
#endif
            wBufLen = (unsigned int)wBufLen << 1;
            if (wBufLen <= 0)
            {
                PRINT_ERR("%s, %d, length overflow!\n", __FUNCTION__, __LINE__);
                return;
            }
            bbuf = (char*)malloc(wBufLen);
            if (NULL == bbuf)
            {
                PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
                return;
            }
            wLen = __dprintf(fmt, ap, pfn_put, bbuf, wBufLen);
        }
        *(bbuf + wLen - 1) = 0;
        (VOID)write(STDOUT, bbuf, wLen);
    }
#else
    (VOID)__dprintf(fmt, ap, pfn_put, bbuf, wBufLen);
#endif
#ifdef USE_STACK_BUFFER
    if (wBufLen != SIZEBUF)
        free(bbuf);  /*lint !e673*/
#else
    free(bbuf);
#endif
} /*lint !e438 !e593*/

#ifdef LOSCFG_SHELL_DMESG
void dmesg_dprintf(const char *fmt, va_list ap)
{
    PUTC_FUNC pfn_put = NULL;
#ifdef LOSCFG_PLATFORM_CONSOLE
    int wLen;
#endif
    int wBufLen;
    char *bbuf = NULL;
#ifdef USE_STACK_BUFFER
    char abuf[SIZEBUF];
    bbuf = abuf;
#else
    bbuf = (char*)malloc(SIZEBUF);
    if (NULL == bbuf)
    {
        PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
        return;
    }
#endif
    wBufLen = SIZEBUF;

#ifdef LOSCFG_PLATFORM_CONSOLE
    if (console_enable() == TRUE)
    {
        pfn_put = NULL;
    }
    wLen = __dprintf(fmt, ap, pfn_put, bbuf, wBufLen);
    if (pfn_put == NULL)
    {
        while (wLen >= wBufLen - 1)
        {
#ifdef USE_STACK_BUFFER
            if (wBufLen != SIZEBUF)
                free(bbuf);  /*lint !e424*/
#else
            free(bbuf);
#endif
            wBufLen <<= 1;
            if (wBufLen <= 0)
            {
                PRINT_ERR("%s, %d, length overflow!\n", __FUNCTION__, __LINE__);
                return;
            }
            bbuf = (char*)malloc(wBufLen);
            if (NULL == bbuf)
            {
                PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
                return;
            }
            wLen = __dprintf(fmt, ap, pfn_put, bbuf, wBufLen);
        }
        *(bbuf + wLen - 1) = 0;
        (VOID)write(STDOUT, bbuf, wLen);
    }
#else
    (VOID)__dprintf(fmt, ap, pfn_put, bbuf, wBufLen);
#endif
#ifdef USE_STACK_BUFFER
    if (wBufLen != SIZEBUF)
        free(bbuf);  /*lint !e673*/
#else
    free(bbuf);
#endif
} /*lint !e438 !e593*/
#endif

#ifdef LOSCFG_PLATFORM_UART_WITHOUT_VFS
__attribute__ ((noinline)) int printf(const char *fmt, ...)
{
    int uwlen;
#ifdef USE_STACK_BUFFER
    char abuf[SIZEBUF];
#else
    char *abuf = NULL;
#endif
    va_list ap;

    va_start(ap, fmt);

#ifndef USE_STACK_BUFFER
    abuf = (char*)malloc(SIZEBUF*sizeof(char));
    if (NULL == abuf)
    {
        PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
        return;
    }
#endif
    (void)memset_s(abuf, SIZEBUF, 0, SIZEBUF);
    uwlen = __dprintf(fmt, ap, (PUTC_FUNC)uart_fputc, abuf, SIZEBUF);

#ifndef USE_STACK_BUFFER
    free(abuf);
#endif
    va_end(ap);

} /*lint !e438*/
#endif

__attribute__ ((noinline)) void los_printf(const char *fmt, ...)
{
    PUTC_FUNC pfn_put = (PUTC_FUNC)uart_fputc;
#ifdef LOSCFG_PLATFORM_CONSOLE
    int uwlen;
#endif
#ifdef USE_STACK_BUFFER
    char abuf[SIZEBUF];
#else
    char *abuf = NULL;
    abuf = (char*)malloc(SIZEBUF*sizeof(char));
    if (NULL == abuf)
    {
        PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
        return;
    }
#endif
    va_list ap;
    va_start(ap, fmt); /*lint !e530*/
    (void)memset_s(abuf, SIZEBUF, 0, SIZEBUF);

#ifdef LOSCFG_PLATFORM_CONSOLE
    if (console_enable() == TRUE)
    {
        pfn_put = NULL;
    }
    uwlen = __dprintf(fmt, ap, pfn_put, abuf, SIZEBUF);
    if (pfn_put == NULL){
        (VOID)write(STDOUT, abuf, uwlen);
    }
#else
    (VOID)__dprintf(fmt, ap, pfn_put, abuf, SIZEBUF);
#endif


#ifndef USE_STACK_BUFFER
    free(abuf);
#endif

    va_end(ap);
} /*lint !e438*/

__attribute__ ((noinline)) void start_printf(const char *fmt, ...)
{
    PUTC_FUNC pfn_put = (PUTC_FUNC)uart_fputc;
#ifdef USE_STACK_BUFFER
    char abuf[SIZEBUF];
#else
    char *abuf = NULL;
    abuf = (char*)malloc(SIZEBUF*sizeof(char));
    if (NULL == abuf)
    {
        PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
        return;
    }
#endif
    va_list ap;
    va_start(ap, fmt); /*lint !e530*/
    (void)memset_s(abuf, SIZEBUF, 0, SIZEBUF);

    (VOID) __dprintf(fmt, ap, pfn_put, abuf, SIZEBUF);

#ifndef USE_STACK_BUFFER
    free(abuf);
#endif

    va_end(ap);
} /*lint !e438*/

__attribute__ ((noinline)) void syslog( int level, const char *fmt, ... )
{
    PUTC_FUNC pfn_put = (PUTC_FUNC)uart_fputc;
#ifdef LOSCFG_PLATFORM_CONSOLE
    int uwlen;
#endif
#ifdef USE_STACK_BUFFER
    char abuf[SIZEBUF];
#else
    char *abuf = NULL;
    abuf = (char*)malloc(SIZEBUF*sizeof(char));
    if (NULL == abuf)
    {
        PRINT_ERR("%s, %d, malloc failed!\n", __FUNCTION__, __LINE__);
        return;
    }
#endif
    va_list ap;
    va_start(ap, fmt); /*lint !e530*/
    (void)memset_s(abuf, SIZEBUF, 0, SIZEBUF);

#ifdef LOSCFG_PLATFORM_CONSOLE
    if (console_enable() == TRUE)
    {
        pfn_put = NULL;
    }
    uwlen = __dprintf(fmt, ap, pfn_put, abuf, SIZEBUF);
    if (pfn_put == NULL){
        (VOID)write(STDOUT, abuf, uwlen);
    }
#else
    (VOID)__dprintf(fmt, ap, pfn_put, abuf, SIZEBUF);
#endif

#ifndef USE_STACK_BUFFER
    free(abuf);
#endif

    va_end(ap);
} /*lint !e438*/
/*lint -e42 -e40 -e52 -e529 -e611 -e578 -e539 -e63*/
